package org.esgl3d.rendering;

import java.util.logging.Level;
import java.util.logging.Logger;

import javax.microedition.khronos.opengles.GL10;
import javax.microedition.khronos.opengles.GL11;

class VertexBuffer extends VertexContainer {
	private static Logger logger = Logger.getLogger(VertexBuffer.class.getName());
	
	private final int vertexBufferId;
	private final GL11 gl;
	
	public VertexBuffer(int sizeInBytes, VertexFormat type, GL11 gl) {
		super(sizeInBytes, type);
		this.gl = gl;
		int[] buffer = new int[1]; 
		gl.glGenBuffers(1, buffer, 0);
		vertexBufferId = buffer[0];
		
		if (logger.isLoggable(Level.FINEST))
			logger.finest(String.format("VBO-Id: %d", vertexBufferId));
	}

	
	void bind() {
		gl.glBindBuffer(GL11.GL_ARRAY_BUFFER, vertexBufferId);
	}
	
	void unbind() {
		gl.glBindBuffer(GL11.GL_ARRAY_BUFFER, 0);
	}
	
	
	@Override
	public void draw(PrimitiveType type, int startVerticeIndex, int numberOfVertices) {
		int glType = GL11.GL_TRIANGLES;
		
		switch (type) {
		case Line:
			glType = GL11.GL_LINES;
			break;
		case Point:
			glType = GL11.GL_POINTS;
			break;
		case TriangleStrip:
			glType = GL11.GL_TRIANGLE_STRIP;
			break;
		case Triangle:
			break;
		}
		
		bind();
		
		if (format.components[VertexFormat.COLOR] > 0) {
			gl.glEnableClientState(GL11.GL_COLOR_ARRAY);
			if (structure == BufferStructure.Stacked)
				gl.glColorPointer(format.components[VertexFormat.COLOR], GL11.GL_FLOAT, 0, format.offsets[VertexFormat.COLOR] * numberOfVertices*4);
			else
				gl.glColorPointer(format.components[VertexFormat.COLOR], GL11.GL_FLOAT, format.totalFloats*4, format.offsets[VertexFormat.COLOR]*4);
		} else
			gl.glDisableClientState(GL11.GL_COLOR_ARRAY);
		
		if (format.components[VertexFormat.NORMAL] > 0) {
			gl.glEnableClientState(GL11.GL_NORMAL_ARRAY);
			if (structure == BufferStructure.Stacked)
				gl.glNormalPointer(GL11.GL_FLOAT, 0, format.offsets[VertexFormat.NORMAL] * numberOfVertices*4);
			else
				gl.glNormalPointer(GL11.GL_FLOAT, format.totalFloats*4, format.offsets[VertexFormat.NORMAL] *4);
		} else
			gl.glDisableClientState(GL11.GL_NORMAL_ARRAY);
		
		if (format.components[VertexFormat.TEXTURE] > 0) {
			gl.glEnableClientState(GL11.GL_TEXTURE_COORD_ARRAY);
			if (structure == BufferStructure.Stacked)
				gl.glTexCoordPointer(format.components[VertexFormat.TEXTURE], GL11.GL_FLOAT, 0, format.offsets[VertexFormat.TEXTURE] * numberOfVertices*4);
			else
				gl.glTexCoordPointer(format.components[VertexFormat.TEXTURE], GL11.GL_FLOAT, format.totalFloats*4, format.offsets[VertexFormat.TEXTURE] *4);
		} else
			gl.glDisableClientState(GL11.GL_TEXTURE_COORD_ARRAY);
		
		if (format.components[VertexFormat.POSITION] > 0) {
			gl.glEnableClientState(GL11.GL_VERTEX_ARRAY);
			if (structure == BufferStructure.Stacked)
				gl.glVertexPointer(format.components[VertexFormat.POSITION], GL11.GL_FLOAT, 0, format.offsets[VertexFormat.POSITION] * numberOfVertices*4);
			else
				gl.glVertexPointer(format.components[VertexFormat.POSITION], GL11.GL_FLOAT, format.totalFloats*4, format.offsets[VertexFormat.POSITION] *4);
		} else
			gl.glDisableClientState(GL11.GL_VERTEX_ARRAY);
				
		gl.glDrawArrays(glType, startVerticeIndex, numberOfVertices);
		unbind();
	}

	@Override
	public void synchronize() {
		
		bind();
		buffer.position(0);
		gl.glBufferData(GL11.GL_ARRAY_BUFFER, buffer.capacity()*4, buffer, GL11.GL_STATIC_DRAW);
	}
}
